/++
 + Module for generating random numbers in a dice-like fashion
 + Authors: Joey Sabey, GameFreak7744@gmail.com
 + Copyright: © Joey Sabey 2012
 + License: MIT License
 +/
module Dice;
import std.random;
import std.conv;

/++
 + Represents a single n-sided dice
 + Example:
 + ---
 + Dice d8 = new Dice(8);
 + d8.roll();
 + writeln(d8.result); //prints a random number between 1 and 8
 + writeln(d8.result); //prints the same number
 + writeln(d8.roll()); //prints a new random number between 1 and 8
 + ---
 +/
class Dice {
	private	ubyte ub_sides;
	/++
	 + Returns: Current number of sides of the dice
	 +/
	@property ubyte sides() {
		return ub_sides;
	}
	/++
	 + Allows you to set the the number of sides of the dice, to anything from 2 to ubyte.max
	 +/
	@property ubyte sides(ubyte x) {
		return ub_sides = checkSides(x);
	}
	private ubyte ub_result;
	/++
	 + Returns: Result of the last roll of the dice
	 +/
	@property ubyte result() {
		return checkResult();
	}
	/++
	 + Creates a new dice with the default number of sides (6)
	 +/
	this() {
		ub_sides = 6;
	}
	/++
	 + Creates a new dice with x sides
	 +/
	this(ubyte x) {
		ub_sides = checkSides(x);
	}
	/++
	 + Returns: Result of the last roll of the dice as a string
	 +/
	override string toString() {
		return to!(string)(checkResult());
	}
	/++
	 + Returns: A random number from 1 to sides
	 +/
	ubyte roll() {
		ub_result = cast(ubyte) uniform(1, ub_sides+1);
		return ub_result;
	}
	private ubyte checkSides(ubyte x) {
		if(x < 2)
			throw new Exception("Dice must have at least 2 sides, passed " ~ to!(string)(x));
		return x;
	}
	private ubyte checkResult() {
		if(ub_result == 0)
			throw new Exception("Dice has not been rolled yet; must call roll() first");
		return ub_result;
	}
}

